/**
 * @module Mscf
 * @description Mscf 微服务通信框架 micro service communication framework
 * @param {*} option
 * 此方法仅供iframe父子页面使用 请勿在一个项目的父子组件中使用
 * mode 表示通讯方式
 * token 表示父子通讯需要的权限验证
 * role 表示应用角色不同，是父窗口还是子窗口
 * watchSelf 表示是否需要监听自己
 */
let Mscf = function (option = { role: 'father' }) {
  if (window.$mscf) {
    console.warn('this instance already exist, you can not create another one')
  } else {
    window.$mscf = this
  }

  this.name = option.name || ''
  this.mode = option.mode || 'iframe'
  this.token = option.token || 'nearby'
  this.role = option.role
  this.watchSelf = option.watchSelf || false
  // 保存当前的消息队列,以key value形式保存
  this.queue = {}

  // 将event listener注册到 mscf上
  this.mountedListener()
}

Mscf.prototype.mountedListener = function () {
  if (window.addEventListener) {
    window.addEventListener('message', this.handleEvent.bind(this), false)
  } else {
    window.attachEvent('onmessage', this.handleEvent.bind(this))
  }
}

Mscf.prototype.on = function (name, callback) {
  if (typeof this.queue[name] === 'undefined') {
    this.queue[name] = []
  }
  // 排除重复的callback
  !this.queue[name].includes(callback) && this.queue[name].push(callback)
}
Mscf.prototype.emit = function (type, targetOrigin, data) {
  const body = Object.assign(
    {},
    {
      type: type,
      data: data,
      origin: this.name,
      token: this.token,
    }
  )
  if (!this.token) {
    throw new Error('nil token is unsupported!')
  }
  // 如果mode为iframe，则使用postMessage方式进行通讯
  if (this.mode === 'iframe') {
    // 判断role角色的不同，选择不一样的postMessage的主体
    if (this.role === 'father') {
      let iframe = document.getElementsByTagName('iframe')[0]
      iframe && iframe.contentWindow.postMessage(body, targetOrigin)
    } else {
      window.top.postMessage(body, targetOrigin)
    }
    this.watchSelf && window.postMessage(body, targetOrigin)
  } else {
    // do another event
  }
}

Mscf.prototype.handleEvent = function (event) {
  let _this = this
  const data = event.data || {}
  if (data && typeof data === 'object' && data.token === this.token) {
    ;(function (data = {}) {
      let event = data.type
      let funcs = _this.queue[event]
      if (typeof funcs === 'undefined') {
        console.warn('error: callback for event [' + event + '] is not defined')
        return
      }
      // 判断queue里面有没有相应的function，如果有，挨个执行
      if (!funcs || !funcs.length) return
      funcs.forEach((func) => {
        if (func instanceof Function) {
          let body = JSON.parse(JSON.stringify(data))
          delete body.token // 此时不再需要token，因为已鉴权
          func.call(this, body)
        }
      })
    })(data)
  }
}
Mscf.prototype.destroy = function () {
  if (window.addEventListener) {
    window.removeEventListener('message', this.handleEvent)
  } else {
    window.detachEvent('onmessage', this.handleEvent)
  }
}

export default Mscf
